﻿using DataProcess.Error;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Http;

namespace DataProcess
{
    /// <summary>
    /// Base32转换
    /// </summary>
    public static class Base32
    {
        private const byte BitsInBlock = 5;

        private const byte BitsInByte = 8;

        private const string Alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ234567";

        private const char Padding = '=';

        public static string Encode(in byte[] input)
        {
            if (input == null)
            {
                throw new ArgumentNullException("input");
            }
            if (input.Length == 0)
            {
                return string.Empty;
            }
            checked
            {
                char[] array = new char[(int)decimal.Ceiling((decimal)input.Length / 5m) * 8];
                int num = 0;
                byte b = 0;
                byte b2 = 5;
                byte[] array2 = input;
                foreach (byte b3 in array2)
                {
                    b = (byte)(b | (b3 >> 8 - unchecked((int)b2)));
                    array[num++] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ234567"[b];
                    if (b2 < 3)
                    {
                        b = (byte)((b3 >> 3 - unchecked((int)b2)) & 0x1F);
                        array[num++] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ234567"[b];
                        b2 = (byte)(unchecked((int)b2) + 5);
                    }
                    b2 = (byte)(unchecked((int)b2) - 3);
                    b = (byte)((b3 << unchecked((int)b2)) & 0x1F);
                }
                if (num != array.Length)
                {
                    array[num++] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ234567"[b];
                }
                while (num < array.Length)
                {
                    array[num++] = '=';
                }
                return new string(array);
            }
        }

        public static byte[] Decode(in string input)
        {
            if (input == null)
            {
                throw new ArgumentNullException("input");
            }
            if (string.IsNullOrEmpty(input))
            {
                return new byte[0];
            }
            char[] array = input.TrimEnd(new char[1]
            {
            '='
            }).ToUpperInvariant().ToCharArray();
            if (array.Any((char x) => "ABCDEFGHIJKLMNOPQRSTUVWXYZ234567".IndexOf(x) == -1))
            {
                throw new ArgumentException("input");
            }
            byte[] array2 = new byte[checked(array.Length * 5) / 8];
            int num = 0;
            byte b = 0;
            byte b2 = 8;
            char[] array3 = array;
            checked
            {
                foreach (char value in array3)
                {
                    int num2 = "ABCDEFGHIJKLMNOPQRSTUVWXYZ234567".IndexOf(value);
                    if (b2 > 5)
                    {
                        int num3 = num2 << unchecked((int)b2) - 5;
                        b = (byte)(b | num3);
                        b2 = (byte)(unchecked((int)b2) - 5);
                    }
                    else
                    {
                        int num3 = num2 >> 5 - unchecked((int)b2);
                        b = (byte)(b | num3);
                        array2[num++] = b;
                        b = unchecked((byte)(num2 << 3 + b2));
                        b2 = (byte)(unchecked((int)b2) + 3);
                    }
                }
                return array2;
            }
        }
    }

    /// <summary>
    /// 通过第三方API封装的中英翻译类
    /// </summary>
    public class Translation
    {
        /// <summary>
        /// 提供替换第三方url的事件
        /// </summary>
        /// <param name="text">需要翻译的文本</param>
        /// <returns></returns>
        public delegate string MakeUrl(string text);
        /// <summary>
        /// 从第三方获取回应信息后的处理
        /// </summary>
        /// <param name="raw">得到的源数据</param>
        /// <returns></returns>
        public delegate string AnalyseWords(string raw);
        /// <summary>
        /// 当指定api路径时
        /// </summary>
        public event MakeUrl OnMakeUrl;
        /// <summary>
        /// 当得到api回应进行分析时
        /// </summary>
        public event AnalyseWords OngetResultWord;
        /// <summary>
        /// 翻译
        /// </summary>
        /// <param name="text">需要翻译的文本</param>
        /// <returns></returns>
        public string Translate(string text)
        {
            return getWord(text);
        }
        /// <summary>
        /// 从得到的源数据中获取结果
        /// </summary>
        /// <param name="text"></param>
        /// <returns></returns>
        protected virtual string getWord(string text)
        {
            string p = getRaw(text).Result;
            if (OngetResultWord != null)
            {
                return OngetResultWord(p);
            }
            return p.Split('\n')[1].TrimStart("result=".ToCharArray());
        }
        /// <summary>
        /// 得到api路径，并获取源数据
        /// </summary>
        /// <param name="text">需要翻译的文本</param>
        /// <returns></returns>
        protected async System.Threading.Tasks.Task<string> getRaw(string text)
        {
            string location = string.Format("http://fanyi.youdao.com/translate?&doctype=text&type=AUTO&i={0}", text);
            if (OnMakeUrl != null)
            {
                location = OnMakeUrl(text);
            }
            HttpClient Client = new HttpClient();
            string res = await Client.GetStringAsync(location);
            return res;
        }

    }


    /// <summary>
    /// 单个可能
    /// </summary>
    public struct ChoiseWords
    {
        public ChoiseWords(string content, int number)
        {
            this.Content = content;
            this.Number = number;
        }
        /// <summary>
        /// 可能元素的名称
        /// </summary>
        public string Content
        {
            get;
            set;
        }
        /// <summary>
        /// 可能发生的次数
        /// </summary>
        public int Number
        {
            get;
            set;
        }
    }
    /// <summary>
    /// 根据全部可能来进行随机抽选的类
    /// </summary>
    public class Lottery
    {
        private List<ChoiseWords> All;
        private int TotalOption
        {
            get
            {
                int t = 0;
                foreach (var i in All)
                {
                    t += i.Number;
                }
                return t;
            }
        }
        private Random random;
        /// <summary>
        /// 所有奖项
        /// </summary>
        public ChoiseWords[] AllChoises
        {
            get => All.ToArray();
            set => All = new List<ChoiseWords>(value);
        }
        /// <summary>
        /// 移除指定奖项
        /// </summary>
        /// <param name="name"></param>
        /// <returns></returns>
        public bool Remove(string name)
        {
            int index = All.FindIndex(delegate (ChoiseWords c)
            {
                return c.Content.Equals(name);
            });
            if (index >= 0)
            {
                All.RemoveAt(index);
                return true;
            }
            else
                return false;
        }
        /// <summary>
        /// 获取指定奖项的中奖概率
        /// </summary>
        /// <param name="name"></param>
        /// <returns></returns>
        public double this[string name]
        {
            get
            {
                int i = FindIndexByName(name);
                if (i >= 0)
                {
                    return GetItemPerCent(i);
                }
                return 0;
            }
        }
        /// <summary>
        /// 根据奖项查找索引
        /// </summary>
        /// <param name="name"></param>
        /// <returns></returns>
        public int FindIndexByName(string name)
        {
            return All.FindIndex(delegate (ChoiseWords v) { return v.Content.Equals(name); });
        }
        /// <summary>
        /// 根据索引获取奖项
        /// </summary>
        /// <param name="index"></param>
        /// <returns></returns>
        public string FindNameByIndex(int index)
        {
            return All[index].Content;
        }
        /// <summary>
        /// 奖项数
        /// </summary>
        public int Count
        {
            get => All.Count;
        }
        /// <summary>
        /// 新增奖项
        /// </summary>
        /// <param name="name"></param>
        /// <param name="number"></param>
        /// <returns></returns>
        public bool Add(string name, int number)
        {
            int index = FindIndexByName(name);

            if (index >= 0)
            {
                return false;
            }
            else
            {
                All.Add(new ChoiseWords(name, number));
                return true;
            }
        }


        void init(ChoiseWords[] choises)
        {
            random = new Random();
            All = new List<ChoiseWords>();
            foreach (ChoiseWords words in choises)
            {
                if (IsNorepeat(words.Content))
                {
                    All.Add(words);
                }
                else
                    throw new ArgumentException("不允许出现重复奖项");
            }
        }
        bool IsNorepeat(string name)
        {
            return FindIndexByName(name) == -1;
        }
        public Lottery(params ChoiseWords[] choises)
        {
            init(choises);
        }
        /// <summary>
        /// 随机抽选
        /// </summary>
        /// <returns></returns>
        public string RandomGet()
        {
            if (All.Count == 0)
            {
                throw new LotteryException("无可用的随机选项");
            }
            int num = random.Next(0, TotalOption);
            int l = 0;
            foreach (var i in All)
            {
                l += i.Number;
                if (num < l)
                {
                    return i.Content;
                }
            }
            throw new LotteryException("抽奖失败");

        }
        /// <summary>
        /// 获取某一项的可能性
        /// </summary>
        /// <param name="index">索引序号</param>
        /// <returns></returns>
        public double GetItemPerCent(int index)
        {
            return All[index].Number / (double)TotalOption;
        }
    }
    public class DataFunctionTester
    {
        /// <summary>
        /// 测试某种操作的所需的时间
        /// </summary>
        /// <param name="test">测试的接口</param>
        /// <returns></returns>
        public TimeSpan SpeedTest(ISpeedTest test)
        {
            DateTime start = DateTime.Now;
            test.TestWork();
            return DateTime.Now - start;
        }
        public TimeSpan SpeedTest(SpeedTestAction test)
        {
            DateTime start = DateTime.Now;
            test();
            return DateTime.Now - start;
        }
        public delegate void SpeedTestAction();
        /// <summary>
        /// 需要计算时间的操作的接口
        /// </summary>
        public interface ISpeedTest
        {
            void TestWork();
        }
    }
}

